const Config = require('../../services/config/config')

// http请求配置
interface RequestConfig {
  /** API地址，以/开头哇 */
  url?: string
  /** Method类型 */
  method?: HttpMethod
  /** 接口返回数据 */
  data?: any
  /** 无TOKEN触发异常捕获时，是否执行异常逻辑 */
  needToken?: boolean
  /** Header头部 */
  header?: object
}

// http请求方法枚举
export enum HttpMethod {
  GET,
  POST
}

// 继承中间类型，把data声明为any
interface AnyResult extends WechatMiniprogram.RequestSuccessCallbackResult {
  data: any
}

// 从中间类型继承一个泛型接口，把data声明为泛型
interface SpecResult<T> extends AnyResult {
  data: T
}

// 声明业务数据类型
export interface MyAwesomeData {
  code: number
  msg: string
  data: any
}

export class HttpRequest {
  private static instance: HttpRequest
  private constructor() {}

  /** 请求函数(单例模式)
   *
   * **注意：**
   * 1. 处理请求的函数记得使用`async/await`
   * 2. `method`需使用`HttpMethod`枚举类，切勿自行定义
   *
   * **示例代码**
   *
   * * ```js
    HttpRequest.getInstance().request({
      url: '/Api',
      method: HttpMethod.GET
    })
   * ```
   */
  public static getInstance(): HttpRequest {
    if (!this.instance) {
      this.instance = new HttpRequest()
    }
    return this.instance
  }

  public request(requestConfig: RequestConfig): Promise<SpecResult<MyAwesomeData>> {
    let _this = this
    //url处理
    requestConfig.url = this.getApiAppName(requestConfig.url)
    return new Promise((resolve, reject) => {
      let header = {
        'content-type': 'application/json'
      }
      wx.request({
        method: requestConfig.method === HttpMethod.GET ? 'GET' : 'POST',
        url: `${requestConfig.url}`,
        data: requestConfig.data,
        header: Object.assign(header, requestConfig?.header),
        success: async function (res: SpecResult<MyAwesomeData>) {
          // let {cookies, data, header, statusCode} = res;
          console.log('发送返回:', res)
          if (_this.handerErrorStatus(res.statusCode, requestConfig)) {
            reject('失败了')
          } else {
            // 200状态码请求正常
            if (res.statusCode == 200) {
              if ([401, 402, 403, 405, 407, 408].indexOf(res.data.code) != -1 && requestConfig.needToken) {
                //
              }
            } else {
              //非200状态码(排除handerErrorStatus特殊处理过的状态码)-数据处理
              res.data = { code: res.statusCode || -404, msg: '服务找不到', data: res.data }
            }
          }
          resolve(res)
        },
        fail: err => reject(err)
      })
    })
  }

  // 处理后端异常状态码
  private handerErrorStatus(statusCode: number, requestConfig: RequestConfig) {
    if (statusCode == 502 || statusCode == 503) {
      if (requestConfig.needToken) {
        wx.showToast({
          title: '服务器开小差',
          icon: 'none'
        })
      }
      return true
    }
    return false
  }

  // 处理url 兼容全路径
  private getApiAppName(url: string | undefined) {
    if (!url) {
      return
    }
    if (typeof url == 'string' && url.indexOf('http') >= 0) {
      return url
    }
    return `${Config.host}${url}`
  }
}
